#!/usr/bin/env python3
# vim: tabstop=4 shiftwidth=4 expandtab

import gemcall
import gemtextparser
import urllib.parse
import sys
from os import getenv

urllib.parse.uses_relative.append("gemini")
urllib.parse.uses_netloc.append("gemini")

def clean(text):
    return text.replace('<','&lt;').replace('>','&gt;')

print("Content-type: text/html\n\n")

if getenv('QUERY_STRING'):
    try:
        baseurl = getenv('QUERY_STRING').split('?')[0]
        response = gemcall.request(baseurl)
        if response.responsecode in [30, 31]:
            newtarget = urllib.parse.urljoin(baseurl, response.meta)
            print(f"<h1>RESPONSE: \"{str(response.responsecode)} {response.meta}\"</h1><p>This address redirects to <a href='{newtarget}'>{newtarget}</a>.</p>")
        elif response.responsecode == 20 and "text/" in response.meta:
            responsetext = response.read(20*1024) # We don't support more than 20kb
            if "text/gemini" in response.meta:
                parser = gemtextparser.GemtextParser()
                preform = False
                listmode = False
                blockquote = False
                for line in parser.parseText(responsetext.decode()):
                    if line.linetype == gemtextparser.LineType.PREFORM:
                        if not preform:
                            print("<pre><code>")
                            preform = True
                        print(clean(line.text()))
                        continue
                    if not line.linetype == gemtextparser.LineType.PREFORM and preform:
                        print("</code></pre>")
                        preform = False

                    if line.linetype == gemtextparser.LineType.LISTITEM:
                        if not listmode:
                            print("<ul>")
                            listmode = True
                        print(f"<li>{clean(line.text())}</li>")
                        continue
                    if not line.linetype == gemtextparser.LineType.LISTITEM and listmode:
                        print("</ul>")
                        listmode = False

                    if line.linetype == gemtextparser.LineType.BLOCKQUOTE:
                        if not blockquote:
                            print("<blockquote>")
                            blockquote = True
                        print(clean(line.text()))
                        continue
                    if not line.linetype == gemtextparser.LineType.BLOCKQUOTE and blockquote:
                        print("</blockquote>")
                        blockquote = False

                    if line.linetype == gemtextparser.LineType.H1 and line.text():
                        print(f"<h1>{clean(line.text())}</h1>")
                        continue
                    if line.linetype == gemtextparser.LineType.H2 and line.text():
                        print(f"<h2>{clean(line.text())}</h2>")
                        continue
                    if line.linetype == gemtextparser.LineType.H3 and line.text():
                        print(f"<h3>{clean(line.text())}</h3>")
                        continue

                    if line.linetype == gemtextparser.LineType.LINK:
                        linkURL = urllib.parse.urljoin(baseurl, clean(line.linkURL().replace("'","")))
                        target = "" if linkURL.startswith("gemini://") else " target='_blank'"
                        if line.text():
                            print(f"<a href='{linkURL}'{target}>{clean(line.text())}</a><br/>")
                        else:
                            print(f"<a href='{linkURL}'{target}>{linkURL}</a><br/>")
                        continue

                    if line.linetype == gemtextparser.LineType.PLAIN:
                        print(f"{clean(line.text())}<br/>")
                if listmode:
                    print("</ul>")
                if blockquote:
                    print("</blockquote>")
                if preform:
                    print("</code></pre>")
                    
            else:
                print("<pre><code>")
                print(clean(responsetext.decode()))
                print("</code></pre>")

        elif response.responsecode == 20:
            print(f"<h1>RESPONSE: \"20 Success\", but...</h1><p>The Wobbly browser only supports text responses, and this response is '{clean(response.meta)}'.</p>")
        elif response.responsecode in [40, 41, 42, 43, 44, 50, 51, 52, 53, 59]:
            print(f"<h1>RESPONSE: \"{str(response.responsecode)} {clean(response.meta)}\"</h1><p>This is an error message from the server. Hopefully it makes sense to you.</p>")
        elif response.responsecode in [60, 61, 62]:
            print(f"<h1>RESPONSE: \"{str(response.responsecode)} {clean(response.meta)}\"</h1><p>The Wobbly browser does not support client certificates. Please install a more full-featured browser to visit this page.</p>")
        elif response.responsecode in [10,11]:
            print(f"<h1>RESPONSE: \"{str(response.responsecode)} {clean(response.meta)}\"</h1><p>The status codes 10 and 11 are requests for user input.</p><p>The only means of submitting user input to a server in gemini is via the so-called QUERY_STRING; the part of a URL that follows after a '?'. The Wobbly browser does not support this for privacy/security reasons. Please install a more full-featured browser to be able to submit data.</p>")

        response.discard()
    except:
        print(f"<h1>Unknown Error</h1><p>Something went wrong when trying to fetch '{getenv('QUERY_STRING')}'. Could not recover.</p>")
else:
    print("<h1>What?</h1><p>I'm sorry, but I don't know what you want me to do without a URL.</p>")
